/**
Copyright (c) 2013 cnova

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

library JMultiboard
    
    globals
        private boolean MB_INIT = false
        
        private JMultiboardHeader headerRandomAccess = 0 
        private JMultiboardCells  tableRandomAccess = 0
        private JMultiboardCell   cellRandomAccess = 0
        private JMultiboardRow    rowRandomAccess = 0
        private JMultiboardColumn columnRandomAccess = 0        
    endglobals
    
    //! textmacro calculate_rgb takes V, R, G, B
        local integer $R$=$V$*0x100
        local integer $G$=$V$*0x10000
        local integer $B$=$V$*0x1000000
        if($R$<0) then
            set $R$ = 0x80+(-(-$R$+0x80000000))/0x1000000
        else
            set $R$ = $R$/0x1000000
        endif
        if($G$<0) then
            set $G$ = 0x80+(-(-$G$+0x80000000))/0x1000000
        else
            set $G$ = $G$/0x1000000
        endif
        if($B$<0) then
            set $B$ = 0x80+(-(-$B$+0x80000000))/0x1000000
        else
            set $B$ = $B$/0x1000000
        endif
    //! endtextmacro
    
    struct JMultiboardCell
        multiboard mb
        integer row
        integer column
        
        private static method create takes nothing returns thistype
            return 0
        endmethod
        static method thisIsAProtectedCreateMethodSoDontGoUsingIt takes nothing returns thistype
            return .allocate()
        endmethod
        
        method setColorEx takes integer red, integer green, integer blue, integer alpha returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            call MultiboardSetItemValueColor(mbitem, red, green, blue, alpha)
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method operator color= takes integer val returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            //! runtextmacro calculate_rgb("val", "red", "green", "blue")
            call MultiboardSetItemValueColor(mbitem, red, green, blue, 255)
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method operator icon= takes string path returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            call MultiboardSetItemIcon(mbitem, path)
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method operator text= takes string s returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            call MultiboardSetItemValue(mbitem, s)
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method operator width= takes integer value returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            call MultiboardSetItemWidth(mbitem, I2R(value)/100.0)
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method operator style= takes string st returns nothing
            local multiboarditem mbitem = MultiboardGetItem(.mb, .row, .column)
            if st == "show both" then
                call MultiboardSetItemStyle(mbitem, true, true)
            elseif st == "show icon" then
                call MultiboardSetItemStyle(mbitem, false, true)
            elseif st == "show text" then
                call MultiboardSetItemStyle(mbitem, true, false)
            else
                call MultiboardSetItemStyle(mbitem, false, false)
            endif
            call MultiboardReleaseItem(mbitem)
            set mbitem = null
        endmethod
        method clone takes nothing returns thistype
            local thistype rval = .allocate()
            set rval.mb = this.mb
            set rval.row = row
            set rval.column = column
            return rval
        endmethod
        method destroy takes nothing returns nothing
            if this !=  cellRandomAccess then
                call .deallocate()
            endif
        endmethod  
    endstruct
    struct JMultiboardCells
        multiboard mb
        private static method create takes nothing returns thistype
            return 0
        endmethod
        static method thisIsAProtectedCreateMethodSoDontGoUsingIt takes nothing returns thistype
            return .allocate()
        endmethod
        
        method setColorEx takes integer red, integer green, integer blue, integer alpha returns nothing
            call MultiboardSetItemsValueColor(.mb, red, green, blue, alpha)
        endmethod
        method operator color= takes integer val returns nothing
            //! runtextmacro calculate_rgb("val", "red", "green", "blue")
            call MultiboardSetItemsValueColor(.mb, red, green, blue, 255)
        endmethod
        method operator icon= takes string path returns nothing
            call MultiboardSetItemsIcon(.mb, path)
        endmethod
        method operator text= takes string value returns nothing
            call MultiboardSetItemsValue(.mb, value)
        endmethod
        method operator width= takes integer value returns nothing
            call MultiboardSetItemsWidth(.mb,I2R(value)/100.0)
        endmethod
        method operator style= takes string st returns nothing
            if st == "show both" then
                call MultiboardSetItemsStyle(.mb, true, true)
            elseif st == "show icon" then
                call MultiboardSetItemsStyle(.mb, false, true)
            elseif st == "show text" then
                call MultiboardSetItemsStyle(.mb, true, false)
            else
                call MultiboardSetItemsStyle(.mb, false, false)
            endif
        endmethod
        method clone takes nothing returns thistype
            local thistype rval = .allocate()
            set rval.mb = this.mb
            return rval
        endmethod
        method destroy takes nothing returns nothing
            if this !=  tableRandomAccess then
                call .deallocate()
            endif
        endmethod  
    endstruct
    struct JMultiboardColumn
        multiboard mb
        integer columnNumber
        integer heightToLoop
        
        private static method create takes nothing returns thistype
            return 0
        endmethod
        static method thisIsAProtectedCreateMethodSoDontGoUsingIt takes nothing returns thistype
            return .allocate()
        endmethod

        method setColorEx takes integer red, integer green, integer blue, integer alpha returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemValueColor(mbitem, red, green, blue, alpha)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator color= takes integer val returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            //! runtextmacro calculate_rgb("val", "red", "green", "blue")
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemValueColor(mbitem, red, green, blue, 255)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator icon= takes string path returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemIcon(mbitem, path)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator text= takes string s returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemValue(mbitem, s)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator width= takes integer value returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            local real w = I2R(value)/100.0
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemWidth(mbitem, w)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator style= takes string st returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .heightToLoop
            local integer col = .columnNumber
            local boolean b1
            local boolean b2
            if st == "show both" then
                set b1 = true
                set b2 = true
            elseif st == "show icon" then
                set b1 = false
                set b2 = true
            elseif st == "show text" then
                set b1 = true
                set b2 = false
            else
                set b1 = false
                set b2 = false
            endif
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, i, col)
                call MultiboardSetItemStyle(mbitem, b1, b2)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        
        method clone takes nothing returns thistype
            local thistype rval = .allocate()
            set rval.mb = this.mb
            set rval.columnNumber = this.columnNumber
            set rval.heightToLoop = this.heightToLoop
            return rval
        endmethod
        method destroy takes nothing returns nothing
            if this !=  columnRandomAccess then
                call .deallocate()
            endif
        endmethod  
    endstruct
    struct JMultiboardRow
        multiboard mb
        integer rowNumber
        integer widthToLoop
        
        private static method create takes nothing returns thistype
            return 0
        endmethod
        static method thisIsAProtectedCreateMethodSoDontGoUsingIt takes nothing returns thistype
            return .allocate()
        endmethod

        method setColorEx takes integer red, integer green, integer blue, integer alpha returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemValueColor(mbitem, red, green, blue, alpha)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator color= takes integer val returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            //! runtextmacro calculate_rgb("val", "red", "green", "blue")
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemValueColor(mbitem, red, green, blue, 255)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator icon= takes string path returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemIcon(mbitem, path)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator text= takes string s returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemValue(mbitem, s)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator width= takes integer value returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            local real w = I2R(value)/100.0
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemWidth(mbitem, w)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        method operator style= takes string st returns nothing
            local integer i = 0
            local multiboarditem mbitem
            local integer max = .widthToLoop
            local integer row = .rowNumber
            local boolean b1
            local boolean b2
            if st == "show both" then
                set b1 = true
                set b2 = true
            elseif st == "show icon" then
                set b1 = false
                set b2 = true
            elseif st == "show text" then
                set b1 = true
                set b2 = false
            else
                set b1 = false
                set b2 = false
            endif
            loop
                exitwhen i >= max
                set mbitem = MultiboardGetItem(.mb, row, i)
                call MultiboardSetItemStyle(mbitem, b1, b2)
                call MultiboardReleaseItem(mbitem)
                set i = i + 1
            endloop
            set mbitem = null
        endmethod
        
        method clone takes nothing returns thistype
            local thistype rval = .allocate()
            set rval.mb = this.mb
            set rval.rowNumber = this.rowNumber
            set rval.widthToLoop = this.widthToLoop
            return rval
        endmethod
        method destroy takes nothing returns nothing
            if this != rowRandomAccess then
                call .deallocate()
            endif
        endmethod
    endstruct
    struct JMultiboardHeader 
        multiboard mb

        private static method create takes nothing returns thistype
            return 0
        endmethod
        static method thisIsAProtectedCreateMethodSoDontGoUsingIt takes nothing returns thistype
            return .allocate()
        endmethod

        method setColorEx takes integer red, integer green, integer blue, integer alpha returns nothing
            call MultiboardSetTitleTextColor(.mb, red, green, blue, alpha)
        endmethod
        method operator color= takes integer val returns nothing
            //! runtextmacro calculate_rgb("val", "red", "green", "blue")
            call MultiboardSetTitleTextColor(.mb, red, green, blue, 255)
        endmethod
        method operator text= takes string value returns nothing
            call MultiboardSetTitleText(.mb, value)
        endmethod
        
        method clone takes nothing returns thistype
            local thistype rval = .allocate()
            set rval.mb = this.mb
            return rval
        endmethod
        method destroy takes nothing returns nothing
            if this !=  headerRandomAccess then
                call .deallocate()
            endif
        endmethod
    endstruct 
    
    struct JMultiboard
        private multiboard mb
        private boolean isVisible
        private player p
        private static thistype array ACTIVE_MB
        

        method operator minimized= takes boolean b returns nothing
            call MultiboardMinimize(.mb, b)
        endmethod
        method operator minimized takes nothing returns boolean
            return IsMultiboardMinimized(.mb)
        endmethod
        method operator width= takes integer w returns nothing
            call MultiboardSetColumnCount(.mb,w)
        endmethod
        method operator width takes nothing returns integer
            return MultiboardGetColumnCount(.mb)
        endmethod
        method operator height= takes integer h returns nothing
            call MultiboardSetRowCount(.mb,h)
        endmethod
        method operator height takes nothing returns integer
            return MultiboardGetRowCount(.mb)
        endmethod
        method operator visible takes nothing returns boolean
            return .isVisible
        endmethod
        method operator visible= takes boolean isVisible returns nothing
            local player p = .p
            local integer pid
            if p == null then
                set pid = 0
                loop
                    exitwhen pid > 11
                    if thistype.ACTIVE_MB[pid] != 0 and thistype.ACTIVE_MB[pid] != this then
                        // some other mb is blocking this one from changing status
                        // so must set that one to false first
                        set thistype.ACTIVE_MB[pid].visible = false
                    endif
                    if isVisible then
                        set thistype.ACTIVE_MB[pid] = this
                    else
                        set thistype.ACTIVE_MB[pid] = 0  
                    endif
                    set pid = pid + 1
                endloop
                set .isVisible = isVisible
                call MultiboardDisplay(.mb, isVisible)
            else
                set pid = GetPlayerId(p)
                if thistype.ACTIVE_MB[pid] != 0 and thistype.ACTIVE_MB[pid] != this then
                    // some other mb is blocking this one from changing status
                    // so must set that one to false first
                    set thistype.ACTIVE_MB[pid].visible = false
                endif
                set .isVisible = isVisible
                if isVisible then
                    set thistype.ACTIVE_MB[pid] = this
                else
                    set thistype.ACTIVE_MB[pid] = 0
                endif
                if GetLocalPlayer() == p then
                    call MultiboardDisplay(.mb, isVisible)
                endif
            endif
            
            set p = null
        endmethod
        
        method cell takes integer row, integer column returns JMultiboardCell
            set cellRandomAccess.mb = .mb 
            set cellRandomAccess.row = row
            set cellRandomAccess.column = column
            return cellRandomAccess
        endmethod
        method row takes integer r returns JMultiboardRow
            set rowRandomAccess.mb = .mb
            set rowRandomAccess.rowNumber = r
            set rowRandomAccess.widthToLoop = .width
            return rowRandomAccess
        endmethod
        method column takes integer c returns JMultiboardColumn
            set columnRandomAccess.mb = .mb
            set columnRandomAccess.columnNumber = c
            set columnRandomAccess.heightToLoop = .height
            return columnRandomAccess
        endmethod
        method operator cells takes nothing returns JMultiboardCells
            set tableRandomAccess.mb = .mb
            return tableRandomAccess
        endmethod
        method operator header takes nothing returns JMultiboardHeader
            set headerRandomAccess.mb = .mb
            return headerRandomAccess
        endmethod
        
        method clear takes nothing returns nothing
            call MultiboardClear(.mb)
        endmethod
 
        static method create takes player p returns thistype
            local thistype this = .allocate()
            local integer i 
            set i = 0

            if MB_INIT == false then
                set headerRandomAccess = JMultiboardHeader.thisIsAProtectedCreateMethodSoDontGoUsingIt()
                set tableRandomAccess = JMultiboardCells.thisIsAProtectedCreateMethodSoDontGoUsingIt()
                set cellRandomAccess = JMultiboardCell.thisIsAProtectedCreateMethodSoDontGoUsingIt()
                set rowRandomAccess = JMultiboardRow.thisIsAProtectedCreateMethodSoDontGoUsingIt()
                set columnRandomAccess = JMultiboardColumn.thisIsAProtectedCreateMethodSoDontGoUsingIt()
                loop
                    exitwhen i > 11
                    set thistype.ACTIVE_MB[i] = 0
                    set i = i + 1
                endloop
                set MB_INIT = true
            endif
            set .isVisible = false
            set .p = p
            set .mb = CreateMultiboard()
            call MultiboardDisplay(.mb, false)
            return this
        endmethod
        method onDestroy takes nothing returns nothing
            call DestroyMultiboard(.mb)
            set .mb = null
        endmethod
    endstruct
endlibrary